package cn.ticsmyc.tools.multiThread.masterSlave;

import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

/**
 * @author Ticsmyc
 * @date 2021-06-04 11:34
 */
public abstract class AbstractMaster<T, V, R> {
    protected volatile Set<? extends SlaveSpec<T, V>> slaves;

    private volatile SubTaskDispatchStrategy<T, V> dispatchStrategy;

    public AbstractMaster() {
    }

    protected void init() {
        slaves = createSlaves();
        dispatchStrategy = newSubTaskDispatcherStrategy();
        for (SlaveSpec<T, V> slave : slaves) {
            slave.init();
        }
    }

    protected R service(Object... param) throws SubTaskFailureException, InterruptedException, ExecutionException {
        final TaskDivideStrategy<V> taskDivideStrategy = newTaskDivideStrategy(param);
        Iterator<Future<T>> iter = dispatchStrategy.dispatch(slaves, taskDivideStrategy);
        for (SlaveSpec<T, V> slave : slaves) {
            slave.shutdown();
        }
        R result = combineResult(iter);
        return result;
    }

    /**
     * 合并子任务执行结果
     *
     * @param iter
     * @return
     */
    protected abstract R combineResult(Iterator<Future<T>> iter) throws ExecutionException, InterruptedException;

    /**
     * 任务拆分策略
     *
     * @param param
     * @return
     */
    protected abstract TaskDivideStrategy<V> newTaskDivideStrategy(Object[] param);

    /**
     * 任务执行子线程
     *
     * @return
     */
    protected abstract Set<? extends SlaveSpec<T, V>> createSlaves();

    protected SubTaskDispatchStrategy<T, V> newSubTaskDispatcherStrategy() {
        return new RoundRobinSubTaskDispatcherStrategy<T, V>();
    }

}
